import NormalLevelBase from "../../Game/Base/LevelBase";
import PageBase from "../../Game/Base/PageBase";
import { GAME_EVENT, PAGE } from "../../Game/Enum";
import { IInGamePagePrams, INormalLevelStruct } from "../../Game/Interface";
import mainRoot from "../../Game/MainRoot";
import bunchInGamePage from "../../Game/Page/bunchInGamePage";
import O1HD from "../../engines/gameEngine";
import { CsvFileKind } from "../../engines/libs/CsvFileKind";
import data_control from "../../engines/libs/data_control";
import level_bunchAnimalGroup from "./level_bunchAnimalGroup";
import level_bunchAnimalItem from "./level_bunchAnimalItem";

const {ccclass, property} = cc._decorator;

@ccclass
export default class level_bunchbunchbunch extends NormalLevelBase {

    @property({type:cc.Node,tooltip:"游戏游玩节点"})
    gameContent:cc.Node = null;

    @property({type:cc.Prefab,tooltip:"组预制体"})
    groupPrefab:cc.Prefab = null;

    @property({type:cc.Prefab,tooltip:"动物预制体"})
    animalPrefab:cc.Prefab = null;

    @property({type:cc.Prefab,tooltip:"门预制体"})
    doorPrefab:cc.Prefab = null;

    @property({type:cc.Prefab,tooltip:"草预制体"})
    glassPrefab:cc.Prefab = null;

    @property({type:cc.Node,tooltip:"门content"})
    doorContent:cc.Node = null;

    @property({type:cc.Node,tooltip:"组content"})
    groupContent:cc.Node = null;

    @property({type:cc.Node,tooltip:"动物content"})
    animalContent:cc.Node = null;

    @property({type:cc.Node,tooltip:"草content"})
    glassContent:cc.Node = null;

    @property({type:cc.Node,tooltip:"点击节点"})
    touchNode:cc.Node = null;

    /**关卡数据 */
    levelData:any = null;

    /**当前选中的节点 */
    curSelectNode:cc.Node = null;

    /**是否可以点击 */
    canTouch:boolean = true;

    /**初始的所有动物 */
    initAnimals:level_bunchAnimalItem[][] = [];

    /**倒计时 */
    countDown:number = 0;

    /**游戏中界面 */
    inGamePage:bunchInGamePage = null;

    /**游戏是否暂停 */
    gamePauseFlag:boolean = false;

    maxCount:number = 0;

    spPathAry:string[] = [
        "chuan_dongwu_1",
        "chuan_dongwu_2",
        "chuan_dongwu_3",
        "chuan_dongwu_4"
    ];

    async Init(info: INormalLevelStruct): Promise<void> {
        this.levelInfo = info;
        this.m_mode = info.mode;
        this.tips = info.tips;
        // console.warn("关卡初始化", this.levelInfo);
        let inGamePrams: IInGamePagePrams = {
            mode: this.m_mode,
            levelInfo:this.levelInfo,
            title: info.title,
            tips: info.tips,
            hideTitle: info.hideTitle
        }
        O1HD.on(GAME_EVENT.ON_BTN_TIPS, this.OnTips.bind(this));
        this.levelData = O1HD.getManagers().csvDataManager.getCsvDataItem(CsvFileKind.CsvFile.bunchbunchbunchLevel,this.levelInfo.level);
        this.countDown = Number(this.levelData["time"]);
        this.spPathAry = data_control.randomSortArray(this.spPathAry);
        let page = await mainRoot.UISystem.OpenPage(PAGE.BUNCH_INGAME_PAGE, inGamePrams);
        this.inGamePage = page as bunchInGamePage;
        this.inGamePage.bindLevel(this);
        await this.loadGroup();
        await this.loadAnimal();
        this.startCountDown();
    }

    async loadGroup(){
        return new Promise<void>(resolve=>{
            let animals:string[] = this.levelData["animal_id"].split("&");
            let maxCount:number = this.maxCount = Number(this.levelData["max_animal_count"]);
            let groupCount = animals.length;
            this.gameContent.scale = animals.length > 4 ? 0.85 : 1;
            let posAry1:cc.Vec2[] = [cc.v2(-285,0),cc.v2(-95,0),cc.v2(95,0),cc.v2(285,0)];
            let posAry2:cc.Vec2[] = [cc.v2(-340,0),cc.v2(-170,0),cc.v2(0,0),cc.v2(170,0),cc.v2(340,0)];
            let posAry:cc.Vec2[] = animals.length > 4 ? posAry2 : posAry1;
            let ary:cc.Node[] = [];
            for(let i = 0; i < groupCount; i++){
                let group : cc.Node = cc.instantiate(this.groupPrefab);
                let gs = group.getComponent(level_bunchAnimalGroup);
                gs.setMaxCount(maxCount);
                gs.bindTag(this,i);
                ary.push(group);
                this.initAnimals[i] = [];
            }
            ary = data_control.randomSortArray(ary);
            for(let i = 0; i < ary.length; i++){
                let pos = posAry[i];
                let group = ary[i];
                group.setParent(this.groupContent);
                group.setPosition(pos);
            }
            let posYAry:number[] = this.getPos(this.maxCount);
            for(let i = 0;i<ary.length;i++){
                let door:cc.Node = cc.instantiate(this.doorPrefab);
                door.parent = this.doorContent;
                door.setPosition(posAry[i].x,posYAry[posYAry.length - 1] + 85);
                door.active = false;
                let glassNode:cc.Node = cc.instantiate(this.glassPrefab);
                glassNode.setParent(this.glassContent);
                glassNode.setPosition(posAry[i]);
                glassNode.height = 5 + 80 * maxCount;
                glassNode.y -= 25;
            }
            this.scheduleOnce(resolve);
        })

    }

    async loadAnimal(){
        if(this.levelData){
            let animals = this.levelData["animal_id"].split("&");
            let animalCounts = this.levelData["animal_count"].split("&");
            let posYAry:number[] = this.getPos(this.maxCount);
            for(let i = 0; i < animals.length; i++){
                let curGroupAnimal = animals[i];
                let curGroupAnimalCount = animalCounts[i];
                let animalTypeAry:string[] = curGroupAnimal.split("|");
                let animalCountAry:string[] = curGroupAnimalCount.split("|");
                let group = this.getOneGroupByTag(i);
                for(let j = animalTypeAry.length - 1;j>=0;j--){
                    let type = animalTypeAry[j];
                    let count = Number(animalCountAry[j]);
                    // console.log(count,"count>>>>>>",j,animalCountAry,animalCounts,this.levelInfo,this.levelData["animal_count"])
                    for(let k = 0; k < count; k++){
                        let animal = cc.instantiate(this.animalPrefab);
                        let as = animal.getComponent(level_bunchAnimalItem);
                        as.bindType(type,this);
                        let pos:cc.Vec2 =  cc.v2(group.node.x,posYAry[group.animalAry.length]);
                        group && group.addAnimal(as);
                        animal.setParent(this.animalContent);
                        // this.scheduleOnce(()=>{
                            animal.setPosition(pos);
                        // })
                        this.initAnimals[i].push(as);
                        await new Promise<void>(resolve=>{
                            resolve();
                        });         
                    }
                }
            }
            this.touchNode.on("touchend",this.onTouchEnd,this);
        }
    }

    async onTouchEnd(e:cc.Event.EventTouch){
        if(!this.canTouch){
            return;
        }
        this.canTouch = false;
        let targetNode:cc.Node = null;
        this.groupContent.children.forEach((n:cc.Node)=>{
            let nBound = n.getBoundingBoxToWorld();
            if(nBound.contains(e.getLocation())){
                targetNode = n;
            }
        });
        if(!targetNode){
            if(this.curSelectNode){
                let cs = this.curSelectNode.getComponent(level_bunchAnimalGroup);
                // 选择动物取消选择
                await this.selectOneGroup(cs,false);
            }
            this.curSelectNode = null;
            this.canTouch = true;
            return;
        }
        O1HD.getManagers().soundMgr.playSound("mainSound/anNiu");
        if(!this.curSelectNode){
            this.curSelectNode = targetNode;
            let cs = this.curSelectNode.getComponent(level_bunchAnimalGroup);
            if(cs.checkGroupIsVaild()){
                this.canTouch = true;
                return;
            }
            // 设置动物为选择状态
            await this.selectOneGroup(cs,true);
        }else{
            let cs = this.curSelectNode.getComponent(level_bunchAnimalGroup);
            let ts = targetNode.getComponent(level_bunchAnimalGroup);
            if(ts.checkGroupIsVaild()){
                this.canTouch = true;
                return;
            }
            if(targetNode.uuid == this.curSelectNode.uuid){
                // 设置动物为非选中状态
                await this.selectOneGroup(cs,false);
                this.curSelectNode = null;
                this.canTouch = true;
                return;
            }
            // 判断能不能放入其他的节点 如果不能则当前选择节点跳到选择的节点
            let cMoveAnimals = cs.getMoveAnimals();
            let pushCardFlag:boolean = false;
            let moveOverFlag:boolean = false;
            let moveAnimals:level_bunchAnimalItem[] = [];
            let moveCount:number = 0;
            await new Promise<void>(resolve=>{
                let a = cMoveAnimals[0];
                if(!ts.checkCanAddAnimal(a)){
                    ts.setHintLb("动\n物\n不\n同\n不\n能\n放\n入");
                    this.canTouch = true;
                    resolve();
                    return;
                }
                if(cMoveAnimals.length <= ts.getCanAddAnimalCount()){
                    // 可以放入
                    for(let i = 0 ; i < cMoveAnimals.length; i++){
                        let animal = cMoveAnimals[i];
                        if(ts.checkCanAddAnimal(animal)){
                            if(i == cMoveAnimals.length - 1){
                                moveOverFlag = true;
                            }
                            pushCardFlag = true;
                            moveAnimals.push(animal);
                            moveCount ++;
                                // 动物取消选择状态
                                // cs.spliceAnimal(animal);
                                // ts.addAnimal(animal);
                                cs.spliceAnimal(animal); 
                                ts.addAnimal(animal);
                                this.pushAnimalToGroupAni(cs,ts,animal).then(()=>{
                                    if( i == moveCount - 1){
                                        resolve();
                                        this.checkGameIsWin();
                                    }
                                });
                        }
                    }
                    if(moveCount == 0){
                        resolve();
                    }
                }else{
                    resolve();
                    // 提示放不进去 满了
                    ts.setHintLb("栅\n栏\n已\n满");
                    return;
                }
            });
            if(!pushCardFlag){
                // 没有移动卡牌 切换选择的卡牌
                this.selectOneGroup(cs,false);
                // await this.selectOneGroup(ts,true);
                this.curSelectNode = null;
            }else{
                // 选中的动物切换为未选中状态
                if(!moveOverFlag){
                    await this.selectOneGroup(cs,false);
                }
                this.curSelectNode = null;
            }
        }
        this.canTouch = true;
    }

    getOneGroupByTag(tag:number){
        return this.groupContent.children.find((node:cc.Node)=>{
            let ns = node.getComponent(level_bunchAnimalGroup);
            return ns.groupTag == tag;
        })?.getComponent(level_bunchAnimalGroup);
    }

    async pushAnimalToGroupAni(oneGroup:level_bunchAnimalGroup,targetGroup:level_bunchAnimalGroup,animal:level_bunchAnimalItem){
        let posYAry:number[] = this.getPos(this.maxCount);
        let ty:number = posYAry[targetGroup.animalAry.length - 1];
        return new Promise<void>(resolve=>{
            let oneX:number = oneGroup.node.x;
            let oneY:number = posYAry[posYAry.length - 1] + 100;
            let targetX:number = targetGroup.node.x;
            let targetY:number = ty;
            let moveSpd:number = 700;
            let oneTime:number = Math.abs(oneY - animal.node.y) / moveSpd;
            let twoTime:number = Math.abs(oneX - targetX) / moveSpd;
            let threeTime:number = (oneY - targetY) / moveSpd;
            cc.tween(animal.node).to(oneTime,{y:oneY}).to(twoTime,{x:targetX}).to(threeTime,{y:targetY}).call(()=>{
                resolve();
            }).start();
        });
    }

    async selectOneGroup(group:level_bunchAnimalGroup,selectFlag:boolean){
        return new Promise<void>(resolve=>{
            let moveAnimals:level_bunchAnimalItem[] = group.getMoveAnimals();
            if(moveAnimals.length <= 0){
                resolve();
                return;
            }
            let lastIndex:number = group.animalAry.length - 1;
            let posYAry:number[] = this.getPos(this.maxCount);
            let ty:number = posYAry[lastIndex];
            let pos:cc.Vec2 = cc.v2(0,ty);
            let dis:number = pos.sub(cc.v2(0,posYAry[posYAry.length -1] + 100)).mag();
            let speed:number = 1000;
            let needTime = dis / speed;
            if(selectFlag){
                for(let animal of moveAnimals){
                    cc.tween(animal.node).by(needTime,{y:dis}).call(resolve).start();
                }
            }else{
                for(let animal of moveAnimals){
                    let index:number = group.checkIndexByAnimal(animal);
                    let posY:number =posYAry[index];
                    needTime = Math.abs(posY - animal.node.y) / speed;
                    console.log(posY,"zmges",animal.node.y,needTime)
                    cc.tween(animal.node).to(needTime,{y:posY}).call(resolve).start();
                } 
            }
        });
    }

    initGame(){
        this.curSelectNode = null;
        let posYAry:number[] = this.getPos(this.maxCount);
        this.doorContent.children.forEach((n:cc.Node)=>{
            n.active = false;
        });
        this.groupContent.children.forEach((n:cc.Node)=>{
            let ns = n.getComponent(level_bunchAnimalGroup);
            ns.closeDoorFlag = false;
        });
        for(let i = 0;i<this.initAnimals.length;i++){
            let group = this.getOneGroupByTag(i);
            group.animalAry = this.initAnimals[i].concat();
            for(let j = 0;j<this.initAnimals[i].length;j++){
                let animal:level_bunchAnimalItem = this.initAnimals[i][j];
                let index = group.checkIndexByAnimal(animal);
                let pos:cc.Vec2 = cc.v2(group.node.x,posYAry[index]);
                animal.node.setPosition(pos);
            }
        }
    }

    OnTips(): void {
        this.inGamePage.hideTipsBtn();
        this.stopCountDown();
        this.startAuto();
    }

    async startAuto(){
        this.initGame();
        this.canTouch = false;
        this.gamePauseFlag = true;
        let stepAry:string[] = this.levelData["hint_step"].split("&");
        for(let i = 0;i<stepAry.length;i++){
            let stepStr = stepAry[i];
            let step = stepStr.split("-");
            let oneGroupId = Number(step[0]) -1;
            let targetGroupId = Number(step[1])-1;
            let oneGroup = this.getOneGroupByTag(oneGroupId);
            let targetGroup = this.getOneGroupByTag(targetGroupId);
            let moveAnimals = oneGroup.getMoveAnimals();
            await new Promise<void>(resolve=>{
                let moveCount:number = 0;
                for(let i = 0 ; i < moveAnimals.length; i++){
                    let animal = moveAnimals[i];
                    if(targetGroup.checkCanAddAnimal(animal)){
                        moveCount ++;
                            // 动物取消选择状态
                            oneGroup.spliceAnimal(animal); 
                            targetGroup.addAnimal(animal);
                            this.pushAnimalToGroupAni(oneGroup,targetGroup,animal).then(()=>{
                                if( i == moveCount - 1){
                                    resolve();
                                    this.checkGameIsWin();
                                }
                            });
                    }else{
                        break;
                    }
                }
                if(moveCount == 0){
                    resolve();
                }
            });
        }
    }

    startCountDown(){
        this.schedule(this.subCountDown,1);
    }

    subCountDown(){
        if(this.gamePauseFlag){
            return;
        }
        this.countDown --;
        this.inGamePage.refrenshCountDown();
        if(this.countDown <= 0){
            this.stopCountDown();
            this.canTouch = false;
            this.Lose(2);
        }
    }

    stopCountDown(){
        this.unschedule(this.subCountDown);
    }

    checkGameIsWin(){
        let isWin:boolean = true;
        this.groupContent.children.forEach((n:cc.Node)=>{
            let ns:level_bunchAnimalGroup = n.getComponent(level_bunchAnimalGroup);
            if(!ns.checkGroupIsVaild() && ns.animalAry.length != 0){
                isWin = false;
            }
        });
        this.closeDoor();
        if(isWin){
            this.Win(2);
        }
    }

    getPos(maxCount:number){
        let posAry:number[] = [];
        let inveter:number = maxCount % 2 == 0 ? 80 / 2 : 0
        if(maxCount % 2 != 0){
            posAry.push(0);
        }
        let roundLength:number = Math.floor(maxCount / 2)
        for(let i = 0;i < roundLength ;i++){
            let one = (i + 1) * 80 - inveter;
            let two =  -((i + 1) * 80 - inveter);
            posAry.push(one);
            posAry.unshift(two);
        }
        return posAry;
    }

    closeDoor(){
        let nodes:cc.Node[] = [];
        this.groupContent.children.forEach((n:cc.Node)=>{
            let ns = n.getComponent(level_bunchAnimalGroup);
            if(ns.checkGroupIsVaild() && !ns.closeDoorFlag){
                nodes.push(n);
                ns.closeDoorFlag = true;
            }
        });
        if(nodes.length > 0){
            for(let node of nodes){
                let sillibing:number = node.getSiblingIndex();
                let door = this.doorContent.children[sillibing];
                let pos:cc.Vec2 = door.getPosition().clone();
                door.y += 200;
                door.active = true;
                cc.tween(door).to( 0.2,{y:pos.y}).call(()=>{
                    this.canvasShark();
                }).start();
            }
        }
    }

    canvasShark(){
        let cameraNode:cc.Node = cc.find("Main Camera");
        if(cameraNode){
            const width = 8;
            let once = cc.tween(cameraNode)
                .by(0.02, { x: width, y: width })
                .by(0.02, { x: 0, y: -width })
                .by(0.02, { x: -width, y: -width })
                .by(0.02, { x: -width, y: 0 })
                .by(0.02, { x: 0, y: width })
                .by(0.02, { x: width, y: 0 });
                //
                cc.tween(cameraNode)
                .then(once)
                .repeat(3)
                .start();
        }
    }


}
